//
//  PlayScene.m
//  lianliankan
//
//

#import "PlayScene.h"
#import "ArrayHelper.h"
#import "DataOperate.h"
#import "DB.h"
#import "UserGame.h"
#import "LevelScene.h"

@implementation PlayScene

@synthesize llkImageData, llkImages, pathSprites, llkSprites;

// 当前关卡
static NSUInteger kCurrentLevelId = 1;
// 每消除一对的得分
static NSUInteger kEarseScore = 100;

// 初始化场景
- (id) init
{
	if((self = [super init]))
	{	
		// 屏幕尺寸
		CGSize screenSize = [[CCDirector sharedDirector] winSize];
		
		// 背景图片
		CCSprite *bg = [CCSprite spriteWithFile:@"background.png"];
		bg.position = ccp(screenSize.width / 2, screenSize.height / 2);
		[self addChild:bg z:0];
        
		// 放置连连看图片
		CCNode *parent = [CCNode node];
		[self addChild:parent z:0 tag:kTagNode];
        
        // 游戏关卡相关属性
        // 本关游戏时长
        currentLevelTime = [[DB fetchGameLevel:kCurrentLevelId] gameTime];
        // 设置道具数量
        refreshNum = [[DB fetchGameLevel:kCurrentLevelId] refreshNumber];
        finderNum = [[DB fetchGameLevel:kCurrentLevelId] finderNumber];
        bombNum = [[DB fetchGameLevel:kCurrentLevelId] bombNumber];
		
		[self playLLK];        
        
		// 进度条背景
		CCSprite *progressBg = [CCSprite spriteWithFile:@"progressbg.png"];
		progressBg.position = ccp(screenSize.width / 2, screenSize.height - 60);
		[self addChild:progressBg z:1];
        
		// 进度条
		timer = [CCProgressTimer progressWithFile:@"progress.png"];
		timerAction = [CCSequence actions:
                       [CCProgressTo actionWithDuration:currentLevelTime percent:100.f], 
                       [CCCallFuncND actionWithTarget:self selector:@selector(showGameEndLayer:data:) data:(void *) NO],
                       nil];
		timer.type = kCCProgressTimerTypeHorizontalBarRL;
		timer.position = ccp(screenSize.width / 2, screenSize.height - 60);
		timer.percentage = 0.0f;
		[self addChild:timer z:2];
		[timer runAction:timerAction];
        
		
		// 当前第几关
		CCLabelTTF *currentLevelNum = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"Level:%d", kCurrentLevelId] fontName:@"Marker Felt" fontSize:16];
		currentLevelNum.position = ccp(35, screenSize.height - 75);
		[self addChild:currentLevelNum z:2];
		
		// 得分
		CCLabelTTF *score = [CCLabelTTF labelWithString:@"Score:0" fontName:@"Marker Felt" fontSize:16];
		score.position = ccp(screenSize.width - 35, screenSize.height - 75);
		[self addChild:score z:2 tag:PlaySceneLayerTagScore];
		
		// 耗时
		CCLabelTTF *timepast = [CCLabelTTF labelWithString:@"Time:0" fontName:@"Marker Felt" fontSize:16];
		timepast.position = ccp(screenSize.width / 2, screenSize.height - 75);
		[self addChild:timepast z:3 tag:PlaySceneLayerTagTimePast];
		
        
		// 底部区域
		CCLayerColor *footerLayer = [CCLayerColor layerWithColor:ccc4(0, 0, 0, 50) width:640 height:50];
		footerLayer.position = ccp(0,0);
		[self addChild:footerLayer z:0];
		
		// 返回
		backMenuItem = [CCMenuItemImage itemFromNormalImage:@"back.png" selectedImage:@"backselected.png" target:self selector:@selector(goBack:)];
		
		CCMenu * ctrlMenu = [CCMenu menuWithItems:backMenuItem, nil];
		ctrlMenu.position = ccp(30, 25);
		[footerLayer addChild:ctrlMenu z:200];
		
		
		// 道具
		// 刷新道具
		propRefreshItem = [CCMenuItemImage itemFromNormalImage:@"refresh.png" selectedImage:@"refreshselected.png" disabledImage:@"refreshdisabled.png" target:self selector:@selector(propRefresh:)];
		
		refreshNumLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:[NSString stringWithFormat:@"%d", refreshNum], kCurrentLevelId] fontName:@"Marker Felt" fontSize:13];
		[propRefreshItem addChild:refreshNumLabel z:1 tag:PlaySceneLayerTagPropsRefresh];
		refreshNumLabel.position = ccp(-2, 7);
		
		// 查找道具
		propFinderItem = [CCMenuItemImage itemFromNormalImage:@"finder.png" selectedImage:@"finderselected.png" disabledImage:@"finderdisabled.png" target:self selector:@selector(propFinder:)];
		finderNumLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:[NSString stringWithFormat:@"%d", finderNum], kCurrentLevelId] fontName:@"Marker Felt" fontSize:13];
		[propFinderItem addChild:finderNumLabel z:1 tag:PlaySceneLayerTagPropsFinder];
		finderNumLabel.position = ccp(-2, 7);
		
		// 炸弹道具
		propBombItem = [CCMenuItemImage itemFromNormalImage:@"bomb.png" selectedImage:@"bombselected.png" disabledImage:@"bombdisabled.png" target:self selector:@selector(propBomb:)];
		bombNumLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:[NSString stringWithFormat:@"%d", bombNum], kCurrentLevelId] fontName:@"Marker Felt" fontSize:13];
		[propBombItem addChild:bombNumLabel z:1 tag:PlaySceneLayerTagPropsBomb];
		bombNumLabel.position = ccp(-2, 7);
		
		CCMenu *propsMenu = [CCMenu menuWithItems:propRefreshItem, propFinderItem, propBombItem, nil];
		[propsMenu alignItemsHorizontallyWithPadding:19.0f];
		propsMenu.position = ccp(screenSize.width - 80, 25);
		[footerLayer addChild:propsMenu z:1];
        
        [self schedule:@selector(timeStep:) interval:1];
	}
    
    self.isTouchEnabled = YES;
	
	return self;
}

//  进入第几关？
+ (void) gotoLevel: (NSUInteger) level
{
	kCurrentLevelId = level;
}


// 开始游戏
- (void) playLLK
{
	[self clearLLK];
	
    leftImages = (NSUInteger) kVerticalItemCount * kHorizontalItemCount * 0.5;
    // 生成关卡数据，第一个元素和最后一个元素表示最外层边框，不使用
    llkImageData = [[DataOperate generateGameData:self rowsnum:kVerticalItemCount colsnum:kHorizontalItemCount datatype:kMaxItems] retain];

	
	// 全部的连连看所用图片
	NSMutableArray *allImages = [NSMutableArray arrayWithCapacity:kMaxItems];
	for (int i = 0; i < kMaxItems; i++) 
	{
		[allImages addObject:[NSString stringWithFormat:@"%i.png", i + 1]];
	}
	llkImages = [[ArrayHelper arrayWithRandomElements:allImages elements:kMaxItems] retain];
	
	// 图片缓存
	[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"fruit.plist"];
	
	// 显示图片
	[self showLLK];
}

// 从游戏数据结构生成图片并显示出来
- (void) showLLK
{
	// 重置数组
	llkSprites = [[NSMutableArray array] retain];
	
	// 最外一圈都是-1，因此下面的2个for都是从1开始，到倒数第二个结束
	for(int i = 0; i < [llkImageData count]; i++)
	{
		NSMutableArray *row = [llkImageData objectAtIndex:i];
		NSMutableArray *rowSprites = [NSMutableArray array];
		
		for (int j = 0; j < [row count]; j ++)
		{
			int spriteIdx = [[NSString stringWithFormat:@"%@", [row objectAtIndex:j]] integerValue];
			if (kEmpty == spriteIdx)
			{
				[rowSprites addObject:[NSNull null]];
				continue;
			}
			
			CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[llkImages objectAtIndex:spriteIdx]];
			ImageNode *sprite = [ImageNode spriteWithSpriteFrame:frame];
			[[self getChildByTag:kTagNode] addChild:sprite z:1 tag:j];
			[rowSprites addObject:sprite];
			
			// 用于计算水平，垂直的图片的position
			// 从左上顶点开始，一行一行，从左到右
			int h = (j - 1) % kHorizontalItemCount;
			int v = kVerticalItemCount - (i - 1) % kVerticalItemCount;
			
			// 连连看图片的左边距：(768 - 64×10 - 1×10)/2
			float left = ([[CCDirector sharedDirector] winSize].width - kImageDimension * kHorizontalItemCount - kPaddingLeft * kHorizontalItemCount) * 0.5;
			
			float x = left + (kImageDimension + 1) * h + kImageDimension * 0.5f;
			float y = kPaddingBottom + (kImageDimension + 1) * v - kImageDimension * 2;

			sprite.position = ccp(x,y);
			
			// 记录信息
			[sprite setData:self row:i col:j type:[[NSString stringWithFormat:@"%@", [row objectAtIndex:j]] integerValue]];
		}
		[llkSprites addObject:rowSprites];
	}
}

// 用于重新生成游戏界面时，清理原图
- (void) clearLLK
{
	for (NSMutableArray *row in llkSprites) 
	{
		for (ImageNode *sprite in row)
		{
			if (![sprite isEqual:[NSNull null]]) 
			{
				[[sprite parent] removeChild:sprite cleanup:YES];
			}
		}
	}
	[llkSprites removeAllObjects];
}


// 暂停游戏
- (void) pauseLLK
{
	// 禁止点击
	self.isTouchEnabled = NO;
	
	// 停止进度条
	[[CCActionManager sharedManager] pauseTarget:timer];
	
	// 返回按钮禁止点击
	[backMenuItem setIsEnabled:NO];
	
	// 暂停时间
	[self unschedule:@selector(timeStep:)];
	
	// 隐藏水果
	for (NSMutableArray *row in llkSprites) 
	{
		for (ImageNode *sprite in row)
		{
			if (![sprite isEqual:[NSNull null]]) 
			{
				[sprite runAction:[CCHide action]];
			}
		}
	}
}

// 刷新连连看
- (void) refreshLLK
{
	for (int row = 0 ; row < [llkSprites count]; row++) 
	{
		for (int col = 0 ; col < [[llkSprites objectAtIndex: row] count]; col++) 
		{
			ImageNode *sprite = [[llkSprites objectAtIndex: row] objectAtIndex: col];
			[[llkImageData objectAtIndex: row] replaceObjectAtIndex: col withObject:[NSString stringWithFormat:@"%d" , ([sprite isEqual: [NSNull null]] ? kEmpty : [sprite imageType])]];
		}
	}
	
	[self clearLLK];
	
	llkImageData = [DataOperate refreshGameData:self gameData:llkImageData];
	[self showLLK];
	// 刷新结束后重置开始点击节点
	beginNode = nil;
}

// 重新开始
- (void) replayLLK
{
	CCScene *s = [CCScene node];
	[s addChild: [PlayScene node]];
	[[CCDirector sharedDirector] replaceScene: s];
	
	// 恢复水果可见
	for (NSMutableArray *row in llkSprites) 
	{
		for (ImageNode *sprite in row)
		{
			if (![sprite isEqual:[NSNull null]]) 
			{
				[sprite runAction:[CCShow action]];
			}
		}
	}
}

// 后退
- (void) goBack: (id)sender
{
	CCScene *sc = [CCScene node];
	[sc addChild:[LevelScene node]];
	
	[[CCDirector sharedDirector] replaceScene:sc];
}


// 触摸结束
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	UITouch *touch = [touches anyObject];
	
	// 获取触摸的位置
	CGPoint location = [touch locationInView: [touch view]];
	CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];
	
	// 处理映射到精灵上的点击
	[self selectSpriteForTouch: (CGPoint)convertedLocation];
	
	return;
}

// 获取点击的精灵，并处理点击事件
- (void) selectSpriteForTouch: (CGPoint)touchLocation
{
	ImageNode *newSprite = nil;
	for (NSMutableArray *row in llkSprites) 
	{
		for (ImageNode *sprite in row)
		{
			if (![sprite isEqual:[NSNull null]]) 
			{
				// 如果点击的位置在此精灵的边界范围内
				if (CGRectContainsPoint([sprite boundingBox], touchLocation))
				{
					newSprite = sprite;
					break;
				}
			}
		}
	}
	
	// 如果未找到被点击的精灵
	if (newSprite == nil) 
	{
		return;
	}
	
	// 如果开始节点未定义
	if (beginNode == nil) 
	{
		beginNode = newSprite;
		[newSprite runAction:[CCTintBy actionWithDuration:.1f red:0 green:100 blue:100]];
	}
	// 如果定义开始节点
	else
	{
		//  不是在同一节点上点击
		if (beginNode != newSprite) 
		{
			// 如果开始和结束节点是同种图片
			if ( [beginNode imageType] == [newSprite imageType]) 
			{
				// 开始和结束节点在数组中的位置
				int begin[2] = {[beginNode row], [beginNode col]};
				int end[2] = {[newSprite row], [newSprite col]};
				
				// 获取两点间的路径
				NSMutableArray *path = [[DataOperate fetchPathBetweenTwoPoint:self beginPosition:begin endPosition:end gameData:llkSprites] retain];
                
				//  如果找到路径
				if ([path count]) 
				{
					// 消除
					[self eliminate:path beginNode:beginNode endNode:newSprite];
				}
				// 未找到路径则将开始节点选中状态消除
				else
				{
					[beginNode runAction:[CCTintBy actionWithDuration:.1f red:0 green:-100 blue:-100]];
				}
				beginNode = nil;
			}
			// 如果点击的第二个图片和第一个图片不同种，将第二个图片定义为开始节点
			else
			{
				[beginNode runAction:[CCTintBy actionWithDuration:.1f red:0 green:-100 blue:-100]];
				beginNode = newSprite;
				[beginNode runAction:[CCTintBy actionWithDuration:.1f red:0 green:100 blue:100]];
			}
		}
	}
}

// 显示路径并消除
- (void) eliminate: (NSMutableArray *)path beginNode: (ImageNode *)begin endNode: (ImageNode *)end
{
	// 在数据数组中去掉开始和结束节点
	[[llkSprites objectAtIndex:[begin row]] replaceObjectAtIndex:[begin col] withObject:[NSNull null]];
	[[llkSprites objectAtIndex:[end row]] replaceObjectAtIndex:[end col] withObject:[NSNull null]];
	
	// 移除开始和结束节点
	[[begin parent] removeChild:begin cleanup:YES];
	[[end parent] removeChild:end cleanup:YES];

	// 音效
	if ([[DB fetchUser] efx]) 
	{
		[[SimpleAudioEngine sharedEngine] playEffect:@"earse.mp3"];
	}
	
	// 每消一次，加100分
	[self updateScore];
    
	leftImages --;

	if (leftImages == 0)
	{
		// 胜利啦
		[self gameWins];
	}
}

// 显示路径并消除
- (void) eliminate: (NSMutableArray *)path
{
	NSArray *beginInfo = [[path objectAtIndex:0] componentsSeparatedByString:@","];
	NSArray *endInfo = [[path objectAtIndex:[path count] - 1] componentsSeparatedByString:@","];
	ImageNode *begin, *end;
	
	begin = [[llkSprites objectAtIndex:[[NSString stringWithFormat:@"%@", [beginInfo objectAtIndex:0]] integerValue]] objectAtIndex: [[NSString stringWithFormat:@"%@", [beginInfo objectAtIndex:1]] integerValue]];
	end = [[llkSprites objectAtIndex:[[NSString stringWithFormat:@"%@", [endInfo objectAtIndex:0]] integerValue]] objectAtIndex: [[NSString stringWithFormat:@"%@", [endInfo objectAtIndex:1]] integerValue]];
	
	if (![begin isEqual: [NSNull null]] && ![end isEqual: [NSNull null]]) {
		[self eliminate:path beginNode:begin endNode:end];
	}
}

// 游戏胜利后的操作
- (void) gameWins
{
	// 游戏得分
	[self scoreCalculate];
	
	// 更新分数显示
	NSString *t = [NSString stringWithFormat:@"Score:%d", gameScore];
	[(CCLabelTTF *)[self getChildByTag:PlaySceneLayerTagScore] setString: t];

    UserGame *userGame = [DB fetchUserGame:kCurrentLevelId];
	userGame.score = gameScore;
	userGame.passed = YES;
	
	// 第一次进行游戏
	if (userGame.gameLevelId == 0)
	{
		userGame.gameLevelId = kCurrentLevelId;
		userGame.spentTime = spentTime;
		
		// 第一次过关，保存本关记录
		[DB newUserGame:userGame];	
	}
	else
	{
		// 用时短，将原记录更新
		if (userGame.spentTime > spentTime)
		{
			userGame.spentTime = spentTime;
			
			[DB updateUserGame:userGame];
		}
	}
    
    User *user = [DB fetchUser];
    
    // 本关是最后一关
	if (kCurrentLevelId >= [DB fetchGameLevelTotal])
	{
		
	}
	else if (kCurrentLevelId == user.gameLevelId)
	{
		// 下一关
		int nextLevel = kCurrentLevelId + 1;
		user.gameLevelId = nextLevel;
		[DB updateUser:user];
	}
    
	id gameWin = [CCCallFuncND actionWithTarget:self selector:@selector(showGameEndLayer:data:) data:(void *) YES];
	[self runAction:gameWin];
}

// 游戏胜利或是失败
- (void) showGameEndLayer : (id) sender data : (void *) data
{	
	// 暂停游戏
	[self pauseLLK];
	
	// 背景层
	CCLayerColor *gameLayer = [CCLayerColor layerWithColor:ccc4(0, 0, 0, 160) width:640 height:960];
	[self addChild:gameLayer z:999];
	
	// 标题
	NSString *title;
	if(data)
	{
		title = @"胜利";
	}
	else
	{
		title = @"失败";
	}
    
    // 屏幕尺寸
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    
	CCLabelTTF *titleLable = [CCLabelTTF labelWithString:title fontName:@"Marker Felt" fontSize:32];
	titleLable.position = ccp(screenSize.width / 2 , screenSize.height - 100);
	[gameLayer addChild:titleLable];
}

// 计时
- (void) timeStep: (ccTime) dt
{
	spentTime += dt;
	
	NSString *t = [NSString stringWithFormat:@"Time:%d", spentTime];
	
	[(CCLabelTTF *)[self getChildByTag:PlaySceneLayerTagTimePast] setString: t];
}

// 计分
- (void) updateScore
{
	gameScore += kEarseScore;
	
	NSString *t = [NSString stringWithFormat:@"Score:%d", gameScore];
	
	[(CCLabelTTF *)[self getChildByTag:PlaySceneLayerTagScore] setString: t];
}

// 计算得分
- (void) scoreCalculate
{
	float e = spentTime / (currentLevelTime / 3);
	float x = 2 / (expf(e) + expf(-e));
	
	// 道具加分
	NSUInteger porpNum = refreshNum + finderNum + bombNum;
	if (porpNum) 
	{
		gameScore += (int) (porpNum * 100);
	}
	
	gameScore += (int) (x * gameScore);
	
	CCLOG(@"gameScore: %d", gameScore);
}

#pragma mark -
#pragma mark 道具

// 刷新道具
- (void) propRefresh : (id) sender
{
	if(refreshNum)
	{
		refreshNum --;
		
		if (refreshNum == 0)
		{
			[self NoProp:sender child:refreshNumLabel];
		}
		else
		{
			// 防止连击
			[self propPreventBatter:sender];
			
			[(CCLabelTTF *)[propRefreshItem getChildByTag:PlaySceneLayerTagPropsRefresh] setString: [NSString stringWithFormat:@"%d", refreshNum]];		
		}	
		
		[self refreshLLK];
	}
}

// 查找道具
- (void) propFinder : (id) sender
{
	if (finderNum > 0) 
	{
		NSMutableArray *path = [DataOperate fetchRandomMatchPath:self gameData:llkSprites];
		
		// 查找到相应路径
		if ([path count])
		{
			finderNum --;
			
			if (finderNum == 0)
			{
				[self NoProp:sender child:finderNumLabel];
			}
			else
			{
				// 防止连击
				[self propPreventBatter:sender];
				
				[(CCLabelTTF *)[propFinderItem getChildByTag:PlaySceneLayerTagPropsFinder] setString: [NSString stringWithFormat:@"%d", finderNum]];
			}
			
			NSArray *beginArray = [[path objectAtIndex:0] componentsSeparatedByString:@","];
			NSArray *endArray = [[path objectAtIndex:[path count] - 1] componentsSeparatedByString:@","];
            
			int begin[2] = {[[NSString stringWithFormat:@"%@", [beginArray objectAtIndex:0]] integerValue], [[NSString stringWithFormat:@"%@", [beginArray objectAtIndex:1]] integerValue]};
			int end[2] = {[[NSString stringWithFormat:@"%@", [endArray objectAtIndex:0]] integerValue], [[NSString stringWithFormat:@"%@", [endArray objectAtIndex:1]] integerValue]};
            
			// 高亮显示两个节点
			ImageNode *beginImageNode = [[llkSprites objectAtIndex:begin[0]] objectAtIndex:begin[1]];
			ImageNode *endImageNode = [[llkSprites objectAtIndex:end[0]] objectAtIndex:end[1]];
            
			[beginImageNode runAction:[CCTintTo actionWithDuration:.1f red:255 green:0 blue:0]];
			[endImageNode runAction:[CCTintTo actionWithDuration:.1f red:255 green:0 blue:0]];
		}
		// 刷新连连看
		else
		{
			[self refreshLLK];
		}
	}
}

// 炸弹道具
- (void) propBomb : (id) sender
{
	if (bombNum > 0)
	{
		NSMutableArray *path = [[DataOperate fetchRandomMatchPath:self gameData:llkSprites] retain];
		
		// 查找到相应路径
		if ([path count])
		{
            bombNum --;
            
            if (bombNum == 0)
			{
				[self NoProp:sender child:bombNumLabel];
			}
			else
			{
				// 防止连击
				[self propPreventBatter:sender];
				
				[(CCLabelTTF *)[propBombItem getChildByTag:PlaySceneLayerTagPropsBomb] setString: [NSString stringWithFormat:@"%d", bombNum]];
                
                [self eliminate:path];
			}
		}
		// 刷新连连看
		else
		{
			[self refreshLLK];
		}
	}
}

// 防止道具连击 
- (void) propPreventBatter : (id) sender
{
	id ac1 = [CCCallFuncN actionWithTarget:self selector:@selector(propDisabled:)];
	id ac2 = [CCCallFuncN actionWithTarget:self selector:@selector(propEnabled:)];
	[sender runAction:[CCSequence actions:ac1, [CCDelayTime actionWithDuration:0.6f], ac2, nil]];
}

// 道具禁用
- (void) propDisabled : (id) sender
{
	[sender setIsEnabled:NO];
}

// 道具可用
- (void) propEnabled : (id) sender
{
	[sender setIsEnabled:YES];
}

// 道具用完了
- (void) NoProp : (id) sender child : (CCLabelTTF *) child
{
	[sender setIsEnabled:NO];
	[sender removeChild:child cleanup:YES];
}

- (void) dealloc
{
	[llkImages release];
	llkImages = nil;
	[llkImageData release];
	llkImageData = nil;
	[llkSprites release];
	llkSprites = nil;
	
	[super dealloc];
}

@end
